home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / test / testrules.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  10.1 KB  |  409 lines

  1. /* ----------------------------------------------------------------
  2.  *               Rule Test Program
  3.  *
  4.  * $Header: /private/postgres/src/test/RCS/testrules.c,v 1.13 1992/06/28 03:48:44 mao Exp $
  5.  * ----------------------------------------------------------------
  6.  */
  7.  
  8. #include <stdio.h>
  9. #include "catalog/catname.h"
  10. #include "access/tupdesc.h"
  11. #include "access/ftup.h"
  12. #include "utils/log.h"
  13. #include "tcop/tcop.h"
  14. #include "rules/prs2.h"
  15. #include "rules/prs2stub.h"
  16. #include "access/heapam.h"
  17. #include "utils/rel.h"
  18. #include "executor/executor.h"
  19.  
  20. /*=======================================================================*/
  21.  
  22. char * RuleLockToString();
  23. RuleLock StringToRuleLock();
  24. EState CreateExecutorState();
  25.  
  26. /*---- testruleplans.c routines...   -----------*/
  27. List makePlanFromQuery();
  28. List makePlanFromFile();
  29. List makePlanFromNLRule();
  30.  
  31. /*---- testtimer.c routines --------------------*/
  32. double getTimer();
  33.  
  34. /*---- routines in this file... ----------------*/
  35. void TestMain();
  36. void testTimePlan();
  37. void testCountPlan();
  38.  
  39. /*=======================================================================*/
  40.  
  41. #define MODE_COUNT    10    /* time query mode... */
  42. #define MODE_TIME    20    /* count tuples mode... */
  43.  
  44. int TESTRULE_DEBUG_FLAG    = 0;
  45.  
  46. extern int Quiet;        /* GLOBAL POSTGRES FLAG */
  47. extern int ShowStats;
  48.  
  49. /*=======================================================================
  50.  *
  51.  * run & time some queries....
  52.  *
  53.  * The program takes many options:
  54.  *
  55.  * -db <dbname>
  56.  *    This specifies the database name and is proccessed by the routine
  57.  *    that calls 'TestMain', so 'TestMain' ignores it
  58.  * -v
  59.  *    Run in verbose mode...
  60.  * -Q
  61.  *    Run postgres in Quiet mode.
  62.  * -nov
  63.  *    TurnOff verbose mode
  64.  * -debug
  65.  *    Print a LOT of debugging stuff!
  66.  * -count
  67.  *    count the number of tuples generated by the query
  68.  * -time
  69.  *    find the time ellapsed to run the query
  70.  * -dummy
  71.  *    before running a query, first run a dummy Xact. This will
  72.  *    have the side effect of initilalizing the system cache,
  73.  *    thus avoiding the significant overhead associated with that...
  74.  * -nodummy
  75.  *    Do not run dummy Xacts from now on
  76.  * -f <filename>
  77.  *    read the plan information from the given file
  78.  *    (see comments in 'makePlanFromFile()' for the file format)
  79.  * -q <query_string>
  80.  *    run the given query
  81.  *    (see also comments in 'makePlanFromString()')
  82.  * -nl <string>
  83.  *    make a plan for rule insertion/deletion simulation
  84.  *    (see comments in 'makePlanFronNLRule()' for the string format)
  85.  * -rp <string>
  86.  *    create a rule plan and add it to pg_prs2plans
  87.  *    see comments in 'addRulePlan' for the string format.
  88.  *
  89.  * NOTE:
  90.  *    The program loops through all the options and executes them
  91.  *    in order. So, it is possible to execute more than one
  92.  *    queries ...
  93.  */
  94.  
  95. void
  96. TestMain(argc, argv)
  97. int argc;
  98. char *argv[];
  99. {
  100.     int i;
  101.     int verboseFlag, dummyFlag, mode;
  102.     List planInfo;
  103.     mode = MODE_TIME;
  104.     verboseFlag = 0;
  105.     dummyFlag = 0;
  106.  
  107.     for (i=1; i<argc; i++) {
  108.     if (!strcmp(argv[i], "-debug")) {
  109.         TESTRULE_DEBUG_FLAG = 1;
  110.     } else if (!strcmp(argv[i], "-Q")) {
  111.         Quiet = 1;
  112.     } else if (!strcmp(argv[i], "-v")) {
  113.         verboseFlag = 1;
  114.     } else if (!strcmp(argv[i], "-nov")) {
  115.         verboseFlag = 0;
  116.     } else if (!strcmp(argv[i], "-dummy")) {
  117.         dummyFlag = 1;
  118.     } else if (!strcmp(argv[i], "-nodummy")) {
  119.         dummyFlag = 0;
  120.     } else if (!strcmp(argv[i], "-count")) {
  121.         mode = MODE_COUNT;
  122.     } else if (!strcmp(argv[i], "-time")) {
  123.         mode = MODE_TIME;
  124.     } else if (!strcmp(argv[i], "-f")) {
  125.         i++;
  126.         if (i >= argc) {
  127.         fprintf(stderr,
  128.             "%s: option -f must be followed by a file name\n",
  129.             argv[0]);
  130.         exitpg(1);
  131.         }
  132.         if (verboseFlag) {
  133.         printf("+++ (FILE=) %s\n", argv[i]);
  134.         }
  135.         planInfo = makePlanFromFile(argv[i]);
  136.         runPlan(planInfo, mode, dummyFlag, verboseFlag);
  137.     } else if (!strcmp(argv[i], "-q")) {
  138.         i++;
  139.         if (i >= argc) {
  140.         fprintf(stderr,
  141.             "%s: option -q must be followed by a string\n",
  142.             argv[0]);
  143.         exitpg(1);
  144.         }
  145.         if (verboseFlag) {
  146.         printf("+++ (QUERY=) %s\n", argv[i]);
  147.         }
  148.         planInfo = makePlanFromQuery(argv[i]);
  149.         runPlan(planInfo, mode, dummyFlag, verboseFlag);
  150.     } else if (!strcmp(argv[i], "-rp")) {
  151.         i++;
  152.         if (i >= argc) {
  153.         fprintf(stderr,
  154.             "%s: option -rp must be followed by a string\n",
  155.             argv[0]);
  156.         exitpg(1);
  157.         }
  158.         if (verboseFlag) {
  159.         printf("+++ (ADDRPLAN=) %s\n", argv[i]);
  160.         }
  161.         addRulePlan(argv[i], verboseFlag);
  162.     } else if (!strcmp(argv[i], "-nl")) {
  163.         i++;
  164.         if (i >= argc) {
  165.         fprintf(stderr,
  166.             "%s: option -nl must be followed by a string\n",
  167.             argv[0]);
  168.         exitpg(1);
  169.         }
  170.         if (verboseFlag) {
  171.         printf("+++ (NLRULE=) %s\n", argv[i]);
  172.         }
  173.         planInfo = makePlanFromNLRule(argv[i]);
  174.         runPlan(planInfo, mode, dummyFlag, verboseFlag);
  175.     } else if (!strcmp(argv[i], "-db")) {
  176.         /*
  177.          * ignore this option and the following database name...
  178.          */
  179.         i++;
  180.     } else {
  181.         fprintf(stderr, "%s: Illegal option: %s\n", argv[0], argv[i]);
  182.         exitpg(1);
  183.     }
  184.     }/*for*/
  185. }
  186.  
  187. /*---------------------------------------------
  188.  *
  189.  * run the plan
  190.  */
  191. runPlan(planInfo, mode, dummyFlag, verboseFlag)
  192. List planInfo;
  193. int mode;
  194. int dummyFlag;
  195. int verboseFlag;
  196. {
  197.     double time;
  198.     int tupleCount;
  199.  
  200.     if (mode == MODE_TIME) {
  201.     testTimePlan(planInfo, dummyFlag, verboseFlag, &time);
  202.     printf("\n");
  203.     printf("=== (time=) %.6f\n", time);
  204.     } else if (mode == MODE_COUNT) {
  205.     testCountPlan(planInfo, dummyFlag, verboseFlag, &time,
  206.     &tupleCount);
  207.     printf("\n");
  208.     printf("=== (tuples=) %d\n", tupleCount);
  209.     printf("=== (time=) %.6f\n", time);
  210.     } else {
  211.     fprintf(stderr,"Illegal mode = %d\n", mode);
  212.     exitpg(1);
  213.     }
  214. }
  215.    
  216.  
  217. /*---------------------------------------------
  218.  * testTimePlan
  219.  *
  220.  * Given a query descriptor, execute the corresponding plan and return
  221.  * the time needed for its completion.
  222.  *
  223.  * There are two flags:
  224.  *    runDummyXact: it runs a dummy Xact to fill in the system cache
  225.  *        to minimize the overhead of the second query.
  226.  *    verbose: if true, then print quite a bit of stuff...
  227.  */
  228. void
  229. testTimePlan(plans, runDummyXact, verbose, timeP)
  230. List plans;
  231. int runDummyXact;
  232. int verbose;
  233. double *timeP;
  234. {
  235.     Portal portal;
  236.     List qDesc;
  237.     LispValue res1, res2, res3;
  238.     EState exState;
  239.     double time;
  240.     int feature;
  241.     List t, planInfo;
  242.  
  243.     /*
  244.      * run a dummy Xact (to fill in sys$$)
  245.      */
  246.     if (runDummyXact) {
  247.     if (verbose) {
  248.         printf("Running dummy Xact...");
  249.     }
  250.         initTimer();
  251.         StartTransactionCommand(portal);
  252.         pg_eval("retrieve (pg_user.all) where pg_user.oid=\"1234\"::oid",
  253.         (char *) NULL, (ObjectId *) NULL, 0);
  254.         CommitTransactionCommand();
  255.     if (verbose) {
  256.         printf("Dummy Xact took = %.6f secs.\n", getTimer());
  257.     }
  258.     }
  259.  
  260.     /*
  261.      * OK now run the plan
  262.      */
  263.     StartTransactionCommand(portal);
  264.  
  265.     ResetUsage();
  266.     initTimer();
  267.     if (verbose) {
  268.     printf("Starting XACT. timer = %.6f\n", getTimer());
  269.     }
  270.  
  271.     foreach (t, plans) {
  272.     planInfo = CAR(t);
  273.  
  274.     feature = CInteger(CAR(planInfo));
  275.     qDesc = CAR(CDR(planInfo));
  276.     exState = CreateExecutorState();
  277.     res1 = ExecMain(qDesc, exState,
  278.                 lispCons(lispInteger(EXEC_START), LispNil));
  279.     res2 = ExecMain(qDesc, exState,
  280.                 lispCons(lispInteger(feature), LispNil));
  281.     res3 = ExecMain(qDesc, exState,
  282.                 lispCons(lispInteger(EXEC_END), LispNil));
  283.     }
  284.     time = getTimer();
  285.     ShowUsage();
  286.     if (verbose) {
  287.     printf("\n+++ (testTimePlan) %.6f (seconds)\n", time);
  288.     }
  289.  
  290.     CommitTransactionCommand();
  291.  
  292.     /*
  293.      * this dummy start + commit has to be there for no apparent reason...
  294.      * (but it *has* to be there, trust me....)
  295.      */
  296.     StartTransactionCommand(portal);
  297.     CommitTransactionCommand();
  298.  
  299.     *timeP = time;
  300.  
  301. }
  302. /*----------------------------------------------
  303.  * testCountPlan
  304.  *
  305.  * Read a plan, execute it & count the #of tuples returned
  306.  * (NOTE, it also returns the time needed...)
  307.  *
  308.  * There are two flags:
  309.  *    runDummyXact: it runs a dummy Xact to fill in the system cache
  310.  *        to minimize the overhead of the second query.
  311.  *    verbose: if true, then print quite a bit of stuff...
  312.  */
  313. void
  314. testCountPlan(plans, runDummyXact, verbose, timeP, tupleCountP)
  315. List plans;
  316. int runDummyXact;
  317. int verbose;
  318. double *timeP;
  319. int *tupleCountP;
  320. {
  321.     Portal portal;
  322.     List qDesc;
  323.     LispValue res1, res2, res3;
  324.     EState exState;
  325.     double time;
  326.     int feature;
  327.     int nTuples;
  328.     HeapTuple resultTuple;
  329.     TupleTableSlot slot;
  330.     TupleDescriptor tupDesc;
  331.     List t, planInfo;
  332.  
  333.     /*
  334.      * run a dummy Xact (to fill in sys$$)
  335.      */
  336.     if (runDummyXact) {
  337.     if (verbose) {
  338.         printf("Running dummy Xact...");
  339.     }
  340.         initTimer();
  341.         StartTransactionCommand(portal);
  342.         pg_eval("retrieve (pg_user.all)",
  343.         (char *) NULL, (ObjectId *) NULL, 0);
  344.         CommitTransactionCommand();
  345.     if (verbose) {
  346.         printf("Dummy Xact took = %.6f secs.\n", getTimer());
  347.     }
  348.     }
  349.  
  350.     /*
  351.      * OK now run the plan
  352.      */
  353.     StartTransactionCommand(portal);
  354.  
  355.     ResetUsage();
  356.     initTimer();
  357.     if (verbose) {
  358.     printf("Starting XACT. timer = %.6f\n", getTimer());
  359.     }
  360.     nTuples = 0;
  361.  
  362.     foreach (t, plans) {
  363.     planInfo = CAR(t);
  364.  
  365.     feature = EXEC_RETONE;
  366.     qDesc = CAR(CDR(planInfo));
  367.     exState = CreateExecutorState();
  368.     res1 = ExecMain(qDesc, exState,
  369.                 lispCons(lispInteger(EXEC_START), LispNil));
  370.     tupDesc = (TupleDescriptor) CADR(res1);
  371.  
  372.     do {
  373.         res2 = ExecMain(qDesc, exState,
  374.                 lispCons(lispInteger(feature), LispNil));
  375.         slot = (TupleTableSlot) res2;
  376.         resultTuple = (HeapTuple) ExecFetchTuple(slot);
  377.         if (resultTuple != NULL) {
  378.         nTuples++;
  379.         if (TESTRULE_DEBUG_FLAG) {
  380.             printf("DEBUG: testCountPlan: tuple no %d\n",nTuples);
  381.             debugtup(resultTuple, tupDesc);
  382.         }
  383.         }
  384.     } while (resultTuple != NULL);
  385.  
  386.     res3 = ExecMain(qDesc, exState,
  387.                 lispCons(lispInteger(EXEC_END), LispNil));
  388.     }
  389.     ShowUsage();
  390.     time = getTimer();
  391.     if (verbose) {
  392.     printf("\n+++ (testCountPlan) %.6f (seconds)\n", time);
  393.     printf("\n+++ (testCountPlan) %d (tuples found)\n", nTuples);
  394.     }
  395.  
  396.     CommitTransactionCommand();
  397.  
  398.     /*
  399.      * this dummy start + commit has to be there for no apparent reason...
  400.      * (but it *has* to be there, trust me....)
  401.      */
  402.     StartTransactionCommand(portal);
  403.     CommitTransactionCommand();
  404.  
  405.     *timeP = time;
  406.     *tupleCountP = nTuples;
  407.  
  408. }
  409.